/****************************************************************
Christian Klugesherz
Novembre 2014
Programme de gestion thermostatique

-----------------------------------------------------------------

Utilisation PIN

   +5V       VCC or +5V      5V
  GND        GND             GND

CC3000      
  Uno Pin    CC3000 Board    Function
  3          INT             Interrupt			(CC3000)
  4          SD_CS           SD Chip Select		(SD)
  5          EN              VBAT EN Module 		(CC3000)
  10         CS              SPI Chip Select 		(CC3000)
  11         MOSI            SPI MOSI			(SD/CC3000)
  12         MISO            SPI MISO			(SD/CC3000)
  13         SCK             SPI Clock 			(SD/CC3000)
RS232
  0      RX
  1      TX
Thermostat
  8

Free
  2
  6
  7
  9
****************************************************************/
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include "utility/debug.h"
#include "utility/socket.h" 

//------------------------------------------------------------------------------------------
// ----------------------------------------DEFINE------------------------------------------- 
//------------------------------------------------------------------------------------------
#define DEBUG 1

#define ADAFRUIT_CC3000_IRQ   3 
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

#define WLAN_SSID       "NETGEAR-1"  
#define WLAN_PASS       "377A2D0C33"

#define WLAN_SECURITY   WLAN_SEC_WPA2	// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2

#define LISTEN_PORT     23      	// What TCP port to listen on for connections. 

//------------------------------------------------------------------------------------------
// ----------------------------------------VARIABLES---------------------------------------- 
//------------------------------------------------------------------------------------------

/* Initialize Wifi Shield CC3000 */
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,SPI_CLOCK_DIVIDER); 

/* Initialize the Ethernet server with the IP address and port to use */
Adafruit_CC3000_Server tcp_server(LISTEN_PORT);

/* Output port to control thermostat */
int pin_thermostat = 8;

/* Static IP address */
  /* Optional: Set a static IP address instead of using DHCP.
     Note that the setStaticIPAddress function will save its state in the CC3000's internal non-volatile memory and the details
     will be used the next time the CC3000 connects to a network.
     This means you only need to call the function once and the CC3000 will remember the connection details.  To switch back
     to using DHCP, call the setDHCP() function (again only needs to be called once).
  */
uint32_t ipAddress = cc3000.IP2U32(192, 168, 1, 30);
uint32_t netMask = cc3000.IP2U32(255, 255, 255, 0);
uint32_t defaultGateway = cc3000.IP2U32(192, 168, 1, 254);
uint32_t dns = cc3000.IP2U32(192,168,1,254);

//---------------------------------------------------------------------------------------------------
//--------------------------------------------- FUNCTION --------------------------------------------
//---------------------------------------------------------------------------------------------------

// ----------------------------------------------------------
// Tries to read the 6-byte MAC address of the CC3000 module
// ----------------------------------------------------------
#ifdef DEBUG
void displayMACAddress(void)
{
  uint8_t macAddress[6];
  
  if(!cc3000.getMacAddress(macAddress))  {
    Serial.println(F("Unable to retrieve MAC Address!\r\n"));
  }  else  {
    Serial.print(F("MAC Address : "));
    cc3000.printHex((byte*)&macAddress, 6);
  }
}
#endif

// ----------------------------------------------------------
// Tries to read the IP address and other connection details
// ----------------------------------------------------------
#ifdef DEBUG
bool displayConnectionDetails(void) {
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  
  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))  {
    Serial.println(F("Unable to retrieve the IP Address!\r\n"));
    return false;
  }  else  {
    Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}
#endif

// ----------------------------------------------------------
// ----------------------------------------------------------
// SETUP
// ----------------------------------------------------------
// ----------------------------------------------------------

void setup(void)
{
  int i;
  
  /* UART */
  Serial.begin(115200);

  /* Output Thermostat */
  pinMode(pin_thermostat,OUTPUT);
  
  /* Initialise the shield module */
  Serial.println(F("\nInitializing..."));
  if (!cc3000.begin()) {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }
  
#ifdef DEBUG
  /* Read MacAddress */
  displayMACAddress();
#endif
  
  /* Delete any old connection data on the module */
  Serial.println(F("\nDeleting old connection profiles"));
  if (!cc3000.deleteProfiles()) {
    Serial.println(F("Failed!"));
    while(1);
  }
  
  /* Optional: Revert back from static IP addres to use DHCP.  */
  /*
  if (!cc3000.setDHCP()) {
    Serial.println(F("Failed to set DHCP!"));
    while(1);
  }
  */
  Serial.println(F("\nSet IP Static Address"));
  if (!cc3000.setStaticIPAddress(ipAddress, netMask, defaultGateway, dns)) {
    Serial.println(F("Failed to set static IP!"));
    while(1);
  }
 
  Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
  Serial.print(F("  --> (needs some more time in static)")); 
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }
  Serial.println(F("Connected!"));

  /* Wait for DHCP to complete */ 
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())  {
    delay(100); // ToDo: Insert a DHCP timeout!
  }  

#ifdef DEBUG
  // Display the IP address DNS, Gateway, etc.
  while (! displayConnectionDetails()) {
    delay(1000);
  }
#endif
 
#ifdef DEBUG
  // ******************************************************
  // You can safely remove this to save some flash memory!
  // ******************************************************
  Serial.println(F("\r\nNOTE: This sketch may cause problems with other sketches"));
  Serial.println(F("since the .disconnect() function is never called, so the"));
  Serial.println(F("AP may refuse connection requests from the CC3000 until a"));
  Serial.println(F("timeout period passes.  This is normal behaviour since"));
  Serial.println(F("there isn't an obvious moment to disconnect with a server.\r\n"));
#endif
  
  // Initialize the server and start listening for connections.
  tcp_server.begin();
  Serial.println(F("Listening for connections..."));

  /* Indicate that all is working well */
  for (i=0;i<10;i++) {
      digitalWrite(pin_thermostat, HIGH);  
      delay(50); 
      digitalWrite(pin_thermostat, LOW);
      delay(50);
  }
  
}

// ----------------------------------------------------------
// ----------------------------------------------------------
// The loop function runs over and over again forever
// ----------------------------------------------------------
// ----------------------------------------------------------
void loop(void){
  char packBuff[30] = "";
  int i;
  char c;
 
        // Return a reference to a client instance which has data available to read.
	Adafruit_CC3000_ClientRef client = tcp_server.available();

	if (client) {
		Serial.println("new client");
              	i = 0;
	        tcp_server.write("\n>>"); 
		while (client.connected()) {
			if (client.available() > 0) {
				// Read a byte 
				c = client.read();
      
				packBuff[i] = c;
				i++;
				if (c == '\n') {
					Serial.println(packBuff);
					i=0;

		                        // If we get the message "PTH"
		                        if (packBuff[0] = 'C' && packBuff[1]=='T' && packBuff[2]=='H') {
			                    digitalWrite(pin_thermostat,HIGH);    
			                    Serial.println("Pin Thermostat ON");   
                        		    tcp_server.write("Thermostat is ON\n>>");
                        		    Serial.println(F("\n\nClient Deconnected"));
		                            client.close();                        
		                        } 
		                        // If we get the message "PTH"
		                        else if (packBuff[0] = 'C' && packBuff[1]=='T' && packBuff[2]=='L') {
			                    digitalWrite(pin_thermostat,LOW);    
			                    Serial.println("Pin Thermostat OFF");  
                        		    tcp_server.write("Thermostat is OFF\n>>");  
                        		    Serial.println(F("\n\nClient Deconnected"));
		                            client.close();
		                        } 
                                        // Close connection
		                        else if (packBuff[0] = 'E' && packBuff[1]=='X' && packBuff[2]=='I' && packBuff[3]=='T') {
                                            Serial.println(F("Closing the connection"));
                        		    tcp_server.write("Connection Closed\n>>");  
                        		    Serial.println(F("\n\nClient Deconnected"));
		                            client.close();
                                        }
                                        else
                                        {
			                    Serial.println("Wrong command");       
                        		    tcp_server.write("Wrong Command\n");   
                        		    tcp_server.write("  CTH --> High \n"); 
                        		    tcp_server.write("  CTL --> Low \n"); 
                        		    tcp_server.write("  EXIT --> Close Connection \n>>"); 
                        		    Serial.println(F("\n\nClient Deconnected"));
		                            client.close();
                                        }
    		                        delay(20);
				}
			}
		}
		Serial.println(F("\n\nClient Deconnected"));
		client.close();
	}
}
